DOM + CSSOM → 렌더 트리 → 레이아웃 → 페인트 → 컴포지트 애니메이션 최적화를 위해 불필요한 레이아웃(리플로)과 페인트(리페인트)를 최소화해야 합니다.
쟁크 현상(Jank)
프레임 드롭이 발생해 애니메이션이 끊기는 현상
브라우저는 초당 **60프레임(60FPS)**을 목표로 렌더링을 수행해야 합니다. 즉, 브라우저 16.67ms(1000ms / 60프레임)안에 모든 작업을 완료해야 부드러운 애니메이션이 구현됩니다. 하지만 리플로와 리페인트가 과도하게 발생하면 **작업 시간 16.67ms를 초과하고, 프레임이 떨어져 끊기는 효과(쟁크 현상)**가 발생합니다.
📌 프레인 드롭 과정
🕒 브라우저는 16.67ms마다 한 프레임을 그려야 함
🏃♂️ 만약 애니메이션 작업이 20ms 걸린다면?
⏳ 16.67ms를 초과 → 한 프레임을 건너뜀 → 30FPS 이하로 떨어짐 → 쟁크 현상 발생!
transform
과 opacity
속성을 활용하면, 레이아웃과 페인트 단계를 건너뛰고 GPU에서 처리되는 컴포지트 단계에서 애니메이션을 수행할 수 있습니다.
해결하기 위해서 하드웨어(GPU) 가속필요
transform과 opacity속성이 이 역할
const BarGraph = styled.div`
position: absolute;
left: 0;
top: 0;
width: ${({width}) => width}%; /* width 변경 → 리플로 발생 */
transition: width 1.5s ease;
height: 100%;
background: ${({isSelected}) => isSelected ? 'rgba(126, 198, 81, 0.7)' : 'rgb(198, 198, 198)'};
z-index: 1;
`
❗width
속성이 변경되면 브라우저는 리플로(Layout 재계산) → 리페인트(Paint) → 컴포지트과정이 필요하므로 성능 저하 발생
❗프레임 드롭(쟁크 현상)이 발생할 가능성이 높음음
const BarGraph = styled.div`
position: absolute;
left: 0;
top: 0;
width: 100%;
transform: scaleX(${({ width }) => width / 100}); /* transform 사용 → GPU 가속 */
transform-origin: center left;
transition: transform 1.5s ease;
height: 100%;
background: ${({isSelected}) => isSelected ? 'rgba(126, 198, 81, 0.7)' : 'rgb(198, 198, 198)'};
z-index: 1;
`
✅ width
대신 transform: scaleX()
을 사용하면 레이아웃 재계산이 필요 없어 리플로가 발생하지 않음.
✅ GPU 가속을 활용하여 성능을 최적화할 수 있음.
✅ 쟁크 현상을 줄이고 부드러운 애니메이션을 구현할 수 있음.
애니메이션 최적화를 적용하기 전에 Chrome DevTools의 Performance 패널을 사용하여 성능을 측정할 수 있습니다.
📌 성능 측정 방법
1. 개발자 도구(F12) → Performance 탭 클릭
2. Record 버튼 클릭 후 애니메이션 실행
3. Frames 섹션에서 Recalculate Style, Layout, Paint 항목 확인
4. 리플로가 자주 발생하는지 확인하고 최적화 적용